iT邦幫忙

2024 iThome 鐵人賽

DAY 22
0
Modern Web

現在就學React.js 系列 第 22

useContext 輕鬆共享資料之props drilling的解方 - Day22

  • 分享至 

  • xImage
  •  

隨著專案的成長,需要將父組件的資料傳遞給深層的子組件。這樣的資料傳遞過程會逐漸變得複雜且繁瑣。React 提供的 useContext Hook 能夠有效解決這資料傳遞的問題,幫助我們在組件樹中更簡單地共享資料,而無需進行繁瑣的屬性傳遞(props drilling)。

什麼是 Props Drilling?

當我們需要將父組件的資料一層層傳遞給子組件時,如果每層組件本身並不使用該資料,這種單純為了傳遞資料的過程被稱為 props drilling。這會讓程式碼變得冗長且難以維護。

https://ithelp.ithome.com.tw/upload/images/20241006/20159895E3ezVMuSlx.png

範例:Props Drilling

import { useState } from "react";

function Component1() {
  const [user, setUser] = useState("Jesse Hall");

  return (
    <>
      <h1>{`Hello ${user}!`}</h1>
      <Component2 user={user} />
    </>
  );
}

function Component2({ user }) {
  return (
    <>
      <h1>Component 2</h1>
      <Component3 user={user} />
    </>
  );
}

function Component3({ user }) {
  return (
    <>
      <h1>Component 3</h1>
      <Component4 user={user} />
    </>
  );
}

function Component4({ user }) {
  return (
    <>
      <h1>Component 4</h1>
      <Component5 user={user} />
    </>
  );
}

function Component5({ user }) {
  return (
    <>
      <h1>Component 5</h1>
      <h2>{`Hello ${user} again!`}</h2>
    </>
  );
}

export default Component1;

在上面的範例中,Component1 中的 user 狀態被傳遞到最內層的 Component5。為了達成這個目的,我們需要將 user 屬性一層層傳遞下去,雖然 Component2, Component3, 和 Component4 並不需要使用這個資料。這就是典型的 props drilling 問題。

useContext 是什麼?

React 的 useContext Hook 讓我們可以輕鬆地在組件間共享資料,而不需要經過層層的 props 傳遞。通過使用 useContext,我們可以讓需要資料的組件直接訪問到最近的 Context Provider 提供的資料,避免了不必要的傳遞過程。

https://ithelp.ithome.com.tw/upload/images/20241006/20159895QYCCr9Eebf.png

如何使用 useContext

  1. Create Context:使用 React.createContext() 創建一個 Context 對象。
  2. Provider 提供資料:使用 Context.Provider 將資料提供給組件樹中的其他組件。
  3. ConsumerContext 資料:使用 useContext Hook 來取得 Context 中的資料。

用 useContext 解決 Props Drilling 問題

讓我們將上面的範例改寫,使用 useContext 來消除 props drilling:

import React, { useState, useContext } from "react";

// 1. 創建 UserContext
const UserContext = React.createContext();

function Component1() {
  const [user, setUser] = useState("Jesse Hall");

  return (
    // 2. 使用 Provider 提供 user 資料給子組件
    <UserContext.Provider value={user}>
      <h1>{`Hello ${user}!`}</h1>
      <Component2 />
    </UserContext.Provider>
  );
}

function Component2() {
  return (
    <>
      <h1>Component 2</h1>
      <Component3 />
    </>
  );
}

function Component3() {
  return (
    <>
      <h1>Component 3</h1>
      <Component4 />
    </>
  );
}

function Component4() {
  return (
    <>
      <h1>Component 4</h1>
      <Component5 />
    </>
  );
}

function Component5() {
  // 3. 使用 useContext 來取得 user 資料
  const user = useContext(UserContext);

  return (
    <>
      <h1>Component 5</h1>
      <h2>{`Hello ${user} again!`}</h2>
    </>
  );
}

export default Component1;

在這個範例中,我們用 UserContext 替代了原本的 props 傳遞,讓 Component5 能夠直接從 Context 中獲取 user 資料,而無需經過每一層組件。這樣一來,不僅解決了 props drilling 的問題,也讓程式碼更加清晰易懂。

什麼時候使用 useContext?

useContext 特別適合在下列情境中使用:

  1. 全局狀態管理:例如用戶資料、主題或語言設定等需要在多個組件中共享的狀態。
  2. 避免冗長的 props 傳遞:當一個資料需要傳遞給多層子組件時,useContext 可以有效簡化這個過程。

useContext 的注意事項

雖然 useContext 提供了一種簡單的方式來共享資料,但在某些情況下,當 context 的資料頻繁更新時,可能會導致不必要的重渲染。如果應用中有頻繁變動的狀態,考慮使用其他狀態管理工具(如Redux) 可能會更合適。

參考資料

後記

本文將會同步更新到我的部落格

黃禎平 – Medium


上一篇
告別不必要的渲染:理解 React useRef -Day21
下一篇
用useMemo優化效能 - Day23
系列文
現在就學React.js 31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言